package com.doodle.common.drawable;

import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;

public class SizedColorDrawable extends Drawable {
	
    private SizedColorState mState;
    private final Paint mPaint = new Paint();
    private boolean mMutated;
	
    /**
     * Creates a new black SizedColorDrawable.
     */
    public SizedColorDrawable() {
        this(null);
    }

    /**
     * Creates a new SizedColorDrawable with the specified color.
     *
     * @param color The color to draw.
     */
    public SizedColorDrawable(int color) {
        this(null);
        setColor(color);
    }
	
	public SizedColorDrawable(int width, int height) {
		this(null);
		setSize(width, height);
	}

    private SizedColorDrawable(SizedColorState state) {
        mState = new SizedColorState(state);
    }

    @Override
    public int getChangingConfigurations() {
        return super.getChangingConfigurations() | mState.mChangingConfigurations;
    }

    /**
     * A mutable BitmapDrawable still shares its Bitmap with any other Drawable
     * that comes from the same resource.
     *
     * @return This drawable.
     */
    @Override
    public Drawable mutate() {
        if (!mMutated && super.mutate() == this) {
            mState = new SizedColorState(mState);
            mMutated = true;
        }
        return this;
    }

    @Override
    public void draw(Canvas canvas) {
        if ((mState.mUseColor >>> 24) != 0) {
            mPaint.setColor(mState.mUseColor);
            canvas.drawRect(getBounds(), mPaint);
        }
    }

    /**
     * Gets the drawable's color value.
     *
     * @return int The color to draw.
     */
    public int getColor() {
        return mState.mUseColor;
    }

    /**
     * Sets the drawable's color value. This action will clobber the results of prior calls to
     * {@link #setAlpha(int)} on this object, which side-affected the underlying color.
     *
     * @param color The color to draw.
     */
    public void setColor(int color) {
        if (mState.mBaseColor != color || mState.mUseColor != color) {
            invalidateSelf();
            mState.mBaseColor = mState.mUseColor = color;
        }
    }

    /**
     * Returns the alpha value of this drawable's color.
     *
     * @return A value between 0 and 255.
     */
    public int getAlpha() {
        return mState.mUseColor >>> 24;
    }

    /**
     * Sets the color's alpha value.
     *
     * @param alpha The alpha value to set, between 0 and 255.
     */
    public void setAlpha(int alpha) {
        alpha += alpha >> 7;   // make it 0..256
        int baseAlpha = mState.mBaseColor >>> 24;
        int useAlpha = baseAlpha * alpha >> 8;
        int oldUseColor = mState.mUseColor;
        mState.mUseColor = (mState.mBaseColor << 8 >>> 8) | (useAlpha << 24);
        if (oldUseColor != mState.mUseColor) {
            invalidateSelf();
        }
    }

    /**
     * Setting a color filter on a SizedColorDrawable has no effect.
     *
     * @param colorFilter Ignore.
     */
    public void setColorFilter(ColorFilter colorFilter) {
    }

    public int getOpacity() {
        switch (mState.mUseColor >>> 24) {
            case 255:
                return PixelFormat.OPAQUE;
            case 0:
                return PixelFormat.TRANSPARENT;
        }
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public ConstantState getConstantState() {
        mState.mChangingConfigurations = getChangingConfigurations();
        return mState;
    }

    final static class SizedColorState extends ConstantState {

    	int mWidth = -1;
    	int mHeight = -1;
    	
        int mBaseColor; // base color, independent of setAlpha()
        int mUseColor;  // basecolor modulated by setAlpha()
        int mChangingConfigurations;

        SizedColorState(SizedColorState state) {
            if (state != null) {
            	mWidth = state.mWidth;
            	mHeight = state.mHeight;
                mBaseColor = state.mBaseColor;
                mUseColor = state.mUseColor;
                mChangingConfigurations = state.mChangingConfigurations;
            }
        }

        @Override
        public Drawable newDrawable() {
            return new SizedColorDrawable(this);
        }

        @Override
        public Drawable newDrawable(Resources res) {
            return new SizedColorDrawable(this);
        }

        @Override
        public int getChangingConfigurations() {
            return mChangingConfigurations;
        }
    }
	
	public void setSize(int width, int height) {
		mState.mWidth = width;
		mState.mHeight = height;
	}
	
	@Override
	public int getIntrinsicWidth() {
		return mState.mWidth;
	}
	
	@Override
	public int getIntrinsicHeight() {
		return mState.mHeight;
	}
}